package com.lablzh.gdxy.controller;

import com.lablzh.gdxy.entity.Student;
import com.lablzh.gdxy.entity.practice.Practice;
import com.lablzh.gdxy.entity.practice.PracticeApply;
import com.lablzh.gdxy.entity.practice.StudentPractice;
import com.lablzh.gdxy.repository.practice.PracticeApplyRepository;
import com.lablzh.gdxy.repository.practice.PracticeRepository;
import com.lablzh.gdxy.repository.practice.StudentPracticeRepository;
import com.lablzh.gdxy.service.FileService;
import com.lablzh.gdxy.service.PracticeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.persistence.criteria.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/practice")
public class PracticeController {

    @Autowired
    private PracticeService practiceService;
    @Autowired
    private FileService fileService;
    @Autowired
    private PracticeRepository practiceRepository;
    @Autowired
    private PracticeApplyRepository practiceApplyRepository;
    @Autowired
    private StudentPracticeRepository studentPracticeRepository;

    @PreAuthorize("hasAnyRole('admin','teacher')")
    @DeleteMapping("/deleteStudent")
    public String deleteStudent(@RequestParam("id") Integer id) {

        PracticeApply practiceApply = practiceApplyRepository.findById(id).orElse(null);
        //Optional<Practice> byId = practiceRepository.findById().orElse(null);
        Practice practice = practiceRepository.findById(practiceApply.getProjectID()).orElse(null);
        practiceRepository.updateRecvAndToSummitAndToReviewAndApplyedById(practice.getId(), practice.getRecv() - 1, practice.getToSummit() - 1, practice.getToReview() - 1, practice.getApplyed() - 1);
        studentPracticeRepository.deleteByProjectIDAndStudentUsername(practice.getId(), practiceApply.getStudentUsername());
        practiceApplyRepository.deleteById(id);

        return "删除成功！";
    }

    /**
     * 定时任务
     */
//    @Scheduled(cron = "0/5 * * * * ?")
    //或直接指定时间间隔，例如：5秒
    @Scheduled(cron = "0 0 0 * * ? ")
    public void configureTasks() {
        LocalDate now = LocalDate.now().plusDays(-1L);
//        System.out.println(now);
        List<Practice> PracticeList = practiceRepository.findAllByTeaChooseDdl(now);
        for (Practice practice : PracticeList) {
            List<PracticeApply> practiceApplyList = practiceApplyRepository.findAllByProjectID(practice.getId());
            for (PracticeApply practiceApply : practiceApplyList) {
                String confirm = practiceService.ddlConfirm(practiceApply.getId());
                if (confirm.equals("选题确认已达上限")) {
                    practiceApplyRepository.updateStatusById(practiceApply.getId(), "未通过");
                }
            }
        }
    }


    /**
     * @param id 生产实习id
     * @return
     */
    @PreAuthorize("hasAnyRole('teacher','admin')")
    @GetMapping("/confirmAll")
    public String confirmAll(@RequestParam("id") Integer id) {
     return practiceService.confirmAll(id);
    }

    /**
     * 创建实习队
     *
     * @param practice
     * @return
     */
    @PreAuthorize("hasRole('admin')")
    @PostMapping("/team")
    public String createTeam(@RequestBody Practice practice) {
        practice.setAudit("未审");
        return practiceService.createTeam(practice);
    }

    /**
     * 删除实习队
     *
     * @param id
     * @return
     */
    @PreAuthorize("hasAnyRole('teacher', 'admin')")
    @DeleteMapping("/team")
    public String deleteTeam(@RequestParam("ID") Integer id) {
        return practiceService.deleteTeam(id);
    }

    /**
     * 修改实习队
     *
     * @return
     */
    @PreAuthorize("hasAnyRole('teacher', 'admin')")
    @PutMapping("/team")
    public String updateTeam(@RequestBody Practice practice) {

        practice.setAudit("未审");
        return practiceService.updateTeam(practice);
    }

    /**
     * 获取所有实习队
     *
     * @return
     */
    @GetMapping("/team")
    public List<Practice> getTeam() {
//        long begin=System.currentTimeMillis();
        List<Practice> practices = practiceService.getTeam();
        return practices;
    }


    /**
     * 多条件查询实习：practiceName， category， college， department， grade
     *
     * @param practice
     * @param page
     * @return
     */
    @PreAuthorize("hasAnyRole('teacher', 'admin','student')")
    @PostMapping("/queryAllPractice")
    public Map getQueryAllPractice(@RequestBody Practice practice,
                                   @RequestParam(name = "page", defaultValue = "0") Integer page) {

        String practiceName = practice.getPracticeName();
        String category = practice.getCategory();
        String college = practice.getCollege();
        String department = practice.getDepartment();
        String grade = practice.getGrade();

        Specification<Practice> spc = new Specification<Practice>() {
            @Override
            public Predicate toPredicate(Root<Practice> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                Predicate predicate = criteriaBuilder.conjunction();
                if ((!StringUtils.isEmpty(practiceName)) && (!practiceName.equals(""))) {
                    predicate.getExpressions().add(criteriaBuilder.like(root.get("practiceName").as(String.class), "%" + practiceName + "%"));
                }
                if ((!StringUtils.isEmpty(category)) && (!category.equals(""))) {
                    predicate.getExpressions().add(criteriaBuilder.like(root.get("category").as(String.class), "%" + category + "%"));
                }
                if ((!StringUtils.isEmpty(college)) && (!college.equals(""))) {
                    predicate.getExpressions().add(criteriaBuilder.like(root.get("college").as(String.class), "%" + college + "%"));
                }
                if ((!StringUtils.isEmpty(department)) && (!department.equals(""))) {
                    predicate.getExpressions().add(criteriaBuilder.like(root.get("department").as(String.class), "%" + department + "%"));
                }
                if ((!StringUtils.isEmpty(grade)) && (!grade.equals(""))) {
                    predicate.getExpressions().add(criteriaBuilder.like(root.get("grade").as(String.class), "%" + grade + "%"));
                }
                return predicate;
            }
        };
        Pageable practicePage = PageRequest.of(page - 1, 20, Sort.by(Sort.Direction.DESC, "id"));
        Page<Practice> all = practiceRepository.findAll(spc, practicePage);
        for (int i = 0; i < all.getContent().size(); i++) {
            Practice practice1 = all.getContent().get(i);
            int numsByNoAudit = practiceApplyRepository.countAllByProjectIDAndStatus(practice1.getId(), "未审");
            practice1.setApplyed(numsByNoAudit);
        }
        Map<String, Object> data = new HashMap<>();
        data.put("totalPage", all.getTotalPages());
        data.put("total", all.getTotalElements());
        data.put("practice", all.getContent());
        return data;
    }


    @GetMapping("/teamByTeacher")
    public List<Practice> getTeamByTeacher() {
        long begin = System.currentTimeMillis();
        List<Practice> practices = practiceService.getTeamByTeacherUsername();
        long end = System.currentTimeMillis();
        System.out.println(end - begin);
        return practices;
    }

    @GetMapping("/practiceByTeacher")
    public List<Practice> getPracticeByTeacher() {
        return practiceService.getPracticeByTeacher();
    }

    /**
     * 根据id获取实习队
     *
     * @param id
     * @return
     */
    @GetMapping("/teamById")
    public Practice getTeamById(@RequestParam("ID") Integer id) {
        return practiceService.getTeamById(id);
    }

    /**
     * 修改开放状态
     *
     * @param id
     * @param status
     * @return
     */
    @PutMapping("/updateStatus")
    public String updateStatus(@RequestParam("ID") Integer id, @RequestParam("status") String status) {
        return practiceService.updataStatus(id, status);
    }

    /**
     * 添加实习大纲
     *
     * @return
     */
    @PostMapping("/outline")
    public Map<String, String> addOutline(HttpServletRequest request) throws IOException {
        String category = request.getParameter("category");
        Integer id = Integer.valueOf(request.getParameter("ID"));
        return practiceService.addOutline(category, id, request);
    }

    @PutMapping("/auditOutline")
    public String auditOutline(@RequestParam("ID") Integer id, @RequestParam("outlineAudit") String outlineAudit) {
        return practiceService.auditOutline(id, outlineAudit);
    }


    /**
     * 申请实习队
     *
     * @param id
     * @return
     */
    @PostMapping("/apply")
    public String apply(@RequestParam("ID") Integer id) {
        return practiceService.apply(id);
    }

    @DeleteMapping("/undo")
    public String undo(@RequestParam("ID") Integer id) {
        return practiceService.undo(id);
    }

    /**
     * 教师获取审核表
     *
     * @return
     */
    @GetMapping("/applyListT")
    public List<PracticeApply> applyListT(@RequestParam("ID") Integer id) {
        return practiceService.applyListT(id);
    }

    /**
     * 获取某实习队审核表
     *
     * @param id
     * @return
     */
    @GetMapping("/applyListA")
    public Map applyListA(@RequestParam("ID") Integer id) {
        List<PracticeApply> practiceApplies = practiceService.applyListA(id);
        long noAudit = practiceApplies.parallelStream().filter(item -> item.getStatus().equals("未审")).count();
        long audit = practiceApplies.parallelStream().filter(item -> item.getStatus().equals("已通过")).count();
        practiceApplies = practiceApplies.parallelStream().filter(item -> !item.getStatus().equals("未通过")).collect(Collectors.toList());
        Map<String, Object> data = new HashMap<>();
        data.put("list", practiceApplies);
        data.put("unAuditNumber", noAudit);
        data.put("sucessNumber", audit);
        return data;
    }

    /**
     * 确认
     *
     * @param id
     * @return
     */
    @PutMapping("/confirm")
    public String confirm(@RequestParam("ID") Integer id) {
        return practiceService.confirm(id);
    }

    /**
     * 退回选择
     *
     * @param id
     * @return
     */
    @PutMapping("/refuse")
    public String refuse(@RequestParam("ID") Integer id) {
        return practiceService.refuse(id);
    }

    /**
     * 学生获取实习申请表
     *
     * @return
     */
    @GetMapping("/practiceApply")
    public List<PracticeApply> getPracticeApply() {
        return practiceService.getPracticeApply();
    }

    /**
     * 学生获取自己的生产实习
     *
     * @return
     */
    @GetMapping("/practiceStudent")
    public List<StudentPractice> getPracticeStudent() {
        return practiceService.getPracticeStudent();
    }

    /**
     * 获取某实习所有学生
     *
     * @param id
     * @return
     */
    @GetMapping("/studentsChoosed")
    public List<StudentPractice> getChoosed(@RequestParam("ID") Integer id) {
        return practiceService.getChoosed(id);
    }

    /**
     * 上传实习报告
     *
     * @param request
     * @return
     * @throws IOException
     */
    @PostMapping("/uploadReport")
    public Map<String, String> uploadReport(HttpServletRequest request) throws IOException {
        String category = request.getParameter("category");
        Integer id = Integer.valueOf(request.getParameter("ID"));
        return practiceService.uploadReport(request, category, id);
    }

    /**
     * 批阅实习报告
     *
     * @param id
     * @param studentUsername
     * @param score
     * @param level
     * @param note
     * @return
     */
    @PutMapping("/review")
    public String review(
            @RequestParam("practiceID") Integer id,
            @RequestParam("studentUsername") String studentUsername,
            @RequestParam("score") Integer score,
            @RequestParam("level") String level,
            @RequestParam("note") String note) {
        return practiceService.review(id, studentUsername, score, level, note);
    }

    /**
     * 获取已提交和未提交的学生
     *
     * @param summit
     * @param id
     * @return
     */
    @GetMapping("/studentBySummit")
    public List<StudentPractice> getStudentBySummit(@RequestParam("summit") String summit,
                                                    @RequestParam("ID") Integer id) {
        return practiceService.getStudentBySummit(summit, id);
    }

    /**
     * 获取已批阅和未批阅的学生
     *
     * @param id
     * @param review
     * @return
     */
    @GetMapping("/studentByReview")
    public List<StudentPractice> getStudentByReview(@RequestParam("ID") Integer id,
                                                    @RequestParam("review") String review) {
        return practiceService.getStudentByReview(review, id);
    }

    /**
     * 查询实习报告成绩
     *
     * @return
     */
    @PreAuthorize("hasAnyRole('teacher','admin')")
    @PostMapping("/queryPerformance")
    public Map<String, Object> export(@RequestBody StudentPractice studentPractice, @RequestParam("page") int page) {
        return practiceService.queryPerformance(studentPractice, page);
    }

    /**
     * 下载报表
     *
     * @param request
     * @param response
     * @return
     * @throws FileNotFoundException
     */
    @PreAuthorize("hasAnyRole('teacher','admin')")
    @PostMapping("/downloadExcel")
    public void downloadExcel(@RequestBody StudentPractice studentPractice,
                              @RequestParam("sort") String sort,
                              HttpServletRequest request,
                              HttpServletResponse response) throws FileNotFoundException {
        practiceService.downloadExcel(studentPractice, request, sort, response);
    }

}
